from django.core.exceptions             import ObjectDoesNotExist
from django.db.models                   import Model
from django.http                        import Http404
from django.views.generic               import GenericViewError
from sitepal.sitemenu.actions.actions   import ACTION_READ_OBJECT
from sitepal.sitemenu.actions.base_view import BaseView

class ObjectView(BaseView):
    def __init__(self,model_class,master_class=None,**kwargs):
        assert issubclass(model_class,Model)
        assert master_class is None or issubclass(master_class,Model)
        self._model_class            = model_class
        self._master_class           = master_class
        self._pk_name = self._pk_arg = self._model_class._meta.pk.name
        self._model_verbose_name     = self._model_class._meta.verbose_name
        if self._master_class:
            for related in self._master_class._meta.get_all_related_objects():
                if related.model == self._model_class:
                    self._pk_arg         = "{0}_{1}".format(related.var_name,self._pk_name)
                    self._acc_name       = related.get_accessor_name()
                    self._master_pk_name = self._master_class._meta.pk.name
                    self._master_pk_arg  = "{0}_{1}".format(self._master_class._meta.object_name.lower(),
                                                            self._master_pk_name)
                    break
            if not hasattr(self,'_acc_name'):
                raise ValueError,"Master and detail model are not related"
        BaseView.__init__(self,**kwargs)

    def get_object(self,request,**kwargs):
        from sitepal.sitemenu.actions import Http403

        if self._pk_arg in kwargs:
            detail_lookup = {"{0}__exact".format(self._pk_name): kwargs[self._pk_arg]}
        else:
            raise GenericViewError,"Object view must be called with an object id."
        try:
            if self._master_class:
                if self._master_pk_arg in kwargs:
                    master_lookup = {"{0}__exact".format(self._master_pk_name): kwargs[self._master_pk_arg]}
                else:
                    raise GenericViewError,"Object view must be called with an object id."
                master  = self._master_class.objects.get(**master_lookup)
                related = getattr(master,self._acc_name)
                obj     = related.get(**detail_lookup)
            else:
                obj = self._model_class.objects.get(**detail_lookup)
            if not self.has_perm(ACTION_READ_OBJECT,request.user,obj):
                raise Http403
            return obj
        except ObjectDoesNotExist:
            raise Http404("No {0} found for {1}".format(model._meta.verbose_name,detail_lookup))

    def handle_get(self,request,**kwargs):
        obj     = self.get_object(request,**kwargs)
        context = self.get_context(request,obj)
        return self.response(request,context)

